home *** CD-ROM | disk | FTP | other *** search
/ PC Advisor 2010 April / PCA177.iso / ESSENTIALS / Firefox Setup.exe / nonlocalized / chrome / browser.jar / content / browser / search / engineManager.js next >
Encoding:
Text File  |  2009-07-15  |  17.3 KB  |  541 lines

  1. //@line 40 "e:\builds\moz2_slave\win32_build\build\browser\components\search\content\engineManager.js"
  2.  
  3. const Ci = Components.interfaces;
  4. const Cc = Components.classes;
  5.  
  6. const ENGINE_FLAVOR = "text/x-moz-search-engine";
  7.  
  8. const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled";
  9.  
  10. var gEngineView = null;
  11.  
  12. var gEngineManagerDialog = {
  13.   init: function engineManager_init() {
  14.     gEngineView = new EngineView(new EngineStore());
  15.  
  16.     var prefService = Cc["@mozilla.org/preferences-service;1"].
  17.                       getService(Ci.nsIPrefBranch);
  18.     var suggestEnabled = prefService.getBoolPref(BROWSER_SUGGEST_PREF);
  19.     document.getElementById("enableSuggest").checked = suggestEnabled;
  20.  
  21.     var tree = document.getElementById("engineList");
  22.     tree.view = gEngineView;
  23.  
  24.     var os = Cc["@mozilla.org/observer-service;1"].
  25.              getService(Ci.nsIObserverService);
  26.     os.addObserver(this, "browser-search-engine-modified", false);
  27.   },
  28.  
  29.   observe: function engineManager_observe(aEngine, aTopic, aVerb) {
  30.     if (aTopic == "browser-search-engine-modified") {
  31.       aEngine.QueryInterface(Ci.nsISearchEngine)
  32.       switch (aVerb) {
  33.       case "engine-added":
  34.         gEngineView._engineStore.addEngine(aEngine);
  35.         gEngineView.rowCountChanged(gEngineView.lastIndex, 1);
  36.         break;
  37.       case "engine-changed":
  38.         gEngineView._engineStore.reloadIcons();
  39.         break;
  40.       case "engine-removed":
  41.       case "engine-current":
  42.         // Not relevant
  43.         return;
  44.       }
  45.       gEngineView.invalidate();
  46.     }
  47.   },
  48.  
  49.   onOK: function engineManager_onOK() {
  50.     // Remove the observer
  51.     var os = Cc["@mozilla.org/observer-service;1"].
  52.              getService(Ci.nsIObserverService);
  53.     os.removeObserver(this, "browser-search-engine-modified");
  54.  
  55.     // Set the preference
  56.     var newSuggestEnabled = document.getElementById("enableSuggest").checked;
  57.     var prefService = Cc["@mozilla.org/preferences-service;1"].
  58.                       getService(Ci.nsIPrefBranch);
  59.     prefService.setBoolPref(BROWSER_SUGGEST_PREF, newSuggestEnabled);
  60.  
  61.     // Commit the changes
  62.     gEngineView._engineStore.commit();
  63.   },
  64.   
  65.   onCancel: function engineManager_onCancel() {
  66.     // Remove the observer
  67.     var os = Cc["@mozilla.org/observer-service;1"].
  68.              getService(Ci.nsIObserverService);
  69.     os.removeObserver(this, "browser-search-engine-modified");
  70.   },
  71.  
  72.   onRestoreDefaults: function engineManager_onRestoreDefaults() {
  73.     var num = gEngineView._engineStore.restoreDefaultEngines();
  74.     gEngineView.rowCountChanged(0, num);
  75.     gEngineView.invalidate();
  76.   },
  77.  
  78.   showRestoreDefaults: function engineManager_showRestoreDefaults(val) {
  79.     document.documentElement.getButton("extra2").disabled = !val;
  80.   },
  81.  
  82.   loadAddEngines: function engineManager_loadAddEngines() {
  83.     this.onOK();
  84.     window.opener.BrowserSearch.loadAddEngines();
  85.     window.close();
  86.   },
  87.  
  88.   remove: function engineManager_remove() {
  89.     gEngineView._engineStore.removeEngine(gEngineView.selectedEngine);
  90.     var index = gEngineView.selectedIndex;
  91.     gEngineView.rowCountChanged(index, -1);
  92.     gEngineView.invalidate();
  93.     gEngineView.selection.select(Math.min(index, gEngineView.lastIndex));
  94.     gEngineView.ensureRowIsVisible(Math.min(index, gEngineView.lastIndex));
  95.     document.getElementById("engineList").focus();
  96.   },
  97.  
  98.   /**
  99.    * Moves the selected engine either up or down in the engine list
  100.    * @param aDir
  101.    *        -1 to move the selected engine down, +1 to move it up.
  102.    */
  103.   bump: function engineManager_move(aDir) {
  104.     var selectedEngine = gEngineView.selectedEngine;
  105.     var newIndex = gEngineView.selectedIndex - aDir;
  106.  
  107.     gEngineView._engineStore.moveEngine(selectedEngine, newIndex);
  108.  
  109.     gEngineView.invalidate();
  110.     gEngineView.selection.select(newIndex);
  111.     gEngineView.ensureRowIsVisible(newIndex);
  112.     this.showRestoreDefaults(true);
  113.     document.getElementById("engineList").focus();
  114.   },
  115.  
  116.   editKeyword: function engineManager_editKeyword() {
  117.     var selectedEngine = gEngineView.selectedEngine;
  118.     if (!selectedEngine)
  119.       return;
  120.  
  121.     var prompt = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  122.                  getService(Ci.nsIPromptService);
  123.     var alias = { value: selectedEngine.alias };
  124.     var strings = document.getElementById("engineManagerBundle");
  125.     var title = strings.getString("editTitle");
  126.     var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
  127.  
  128.     while (prompt.prompt(window, title, msg, alias, null, { })) {
  129.       var bduplicate = false;
  130.       var eduplicate = false;
  131.  
  132.       if (alias.value != "") {
  133.         try {
  134.           let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  135.                        getService(Ci.nsINavBookmarksService);
  136.           if (bmserv.getURIForKeyword(alias.value))
  137.             bduplicate = true;
  138.         } catch(ex) {}
  139.  
  140.         // Check for duplicates in changes we haven't committed yet
  141.         let engines = gEngineView._engineStore.engines;
  142.         for each (let engine in engines) {
  143.           if (engine.alias == alias.value && 
  144.               engine.name != selectedEngine.name) {
  145.             eduplicate = true;
  146.             break;
  147.           }
  148.         }
  149.       }
  150.  
  151.       // Notify the user if they have chosen an existing engine/bookmark keyword
  152.       if (eduplicate || bduplicate) {
  153.         var dtitle = strings.getString("duplicateTitle");
  154.         var bmsg = strings.getString("duplicateBookmarkMsg");
  155.         var emsg = strings.getFormattedString("duplicateEngineMsg",
  156.                                               [engine.name]);
  157.  
  158.         prompt.alert(window, dtitle, (eduplicate) ? emsg : bmsg);
  159.       } else {
  160.         gEngineView._engineStore.changeEngine(selectedEngine, "alias",
  161.                                               alias.value);
  162.         gEngineView.invalidate();
  163.         break;
  164.       }
  165.     }
  166.   },
  167.  
  168.   onSelect: function engineManager_onSelect() {
  169.     // buttons only work if an engine is selected and it's not the last engine
  170.     var disableButtons = (gEngineView.selectedIndex == -1) ||
  171.                          (gEngineView.lastIndex == 0);
  172.     var lastSelected = (gEngineView.selectedIndex == gEngineView.lastIndex);
  173.     var firstSelected = (gEngineView.selectedIndex == 0);
  174.     var noSelection = (gEngineView.selectedIndex == -1);
  175.  
  176.     document.getElementById("cmd_remove").setAttribute("disabled",
  177.                                                        disableButtons);
  178.  
  179.     document.getElementById("cmd_moveup").setAttribute("disabled",
  180.                                             disableButtons || firstSelected);
  181.  
  182.     document.getElementById("cmd_movedown").setAttribute("disabled",
  183.                                              disableButtons || lastSelected);
  184.     document.getElementById("cmd_editkeyword").setAttribute("disabled",
  185.                                                             noSelection);
  186.   }
  187. };
  188.  
  189. var gDragObserver = {
  190.   onDragStart: function (aEvent, aXferData, aDragAction) {
  191.     var selectedIndex = gEngineView.selectedIndex;
  192.     if (selectedIndex == -1)
  193.       return;
  194.  
  195.     aXferData.data = new TransferData();
  196.     aXferData.data.addDataForFlavour(ENGINE_FLAVOR, selectedIndex.toString());
  197.  
  198.     aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_MOVE;
  199.   },
  200.   onDrop: function (aEvent, aXferData, aDragSession) { },
  201.   onDragExit: function (aEvent, aDragSession) { },
  202.   onDragOver: function (aEvent, aFlavour, aDragSession) { },
  203.   getSupportedFlavours: function() { return null; }
  204. };
  205.  
  206. // "Operation" objects
  207. function EngineMoveOp(aEngineClone, aNewIndex) {
  208.   if (!aEngineClone)
  209.     throw new Error("bad args to new EngineMoveOp!");
  210.   this._engine = aEngineClone.originalEngine;
  211.   this._newIndex = aNewIndex;
  212. }
  213. EngineMoveOp.prototype = {
  214.   _engine: null,
  215.   _newIndex: null,
  216.   commit: function EMO_commit() {
  217.     var searchService = Cc["@mozilla.org/browser/search-service;1"].
  218.                         getService(Ci.nsIBrowserSearchService);
  219.     searchService.moveEngine(this._engine, this._newIndex);
  220.   }
  221. }
  222.  
  223. function EngineRemoveOp(aEngineClone) {
  224.   if (!aEngineClone)
  225.     throw new Error("bad args to new EngineRemoveOp!");
  226.   this._engine = aEngineClone.originalEngine;
  227. }
  228. EngineRemoveOp.prototype = {
  229.   _engine: null,
  230.   commit: function ERO_commit() {
  231.     var searchService = Cc["@mozilla.org/browser/search-service;1"].
  232.                         getService(Ci.nsIBrowserSearchService);
  233.     searchService.removeEngine(this._engine);
  234.   }
  235. }
  236.  
  237. function EngineUnhideOp(aEngineClone, aNewIndex) {
  238.   if (!aEngineClone)
  239.     throw new Error("bad args to new EngineUnhideOp!");
  240.   this._engine = aEngineClone.originalEngine;
  241.   this._newIndex = aNewIndex;
  242. }
  243. EngineUnhideOp.prototype = {
  244.   _engine: null,
  245.   _newIndex: null,
  246.   commit: function EUO_commit() {
  247.     this._engine.hidden = false;
  248.     var searchService = Cc["@mozilla.org/browser/search-service;1"].
  249.                         getService(Ci.nsIBrowserSearchService);
  250.     searchService.moveEngine(this._engine, this._newIndex);
  251.   }
  252. }
  253.  
  254. function EngineChangeOp(aEngineClone, aProp, aValue) {
  255.   if (!aEngineClone)
  256.     throw new Error("bad args to new EngineChangeOp!");
  257.  
  258.   this._engine = aEngineClone.originalEngine;
  259.   this._prop = aProp;
  260.   this._newValue = aValue;
  261. }
  262. EngineChangeOp.prototype = {
  263.   _engine: null,
  264.   _prop: null,
  265.   _newValue: null,
  266.   commit: function ECO_commit() {
  267.     this._engine[this._prop] = this._newValue;
  268.   }
  269. }
  270.  
  271. function EngineStore() {
  272.   var searchService = Cc["@mozilla.org/browser/search-service;1"].
  273.                       getService(Ci.nsIBrowserSearchService);
  274.   this._engines = searchService.getVisibleEngines({}).map(this._cloneEngine);
  275.   this._defaultEngines = searchService.getDefaultEngines({}).map(this._cloneEngine);
  276.  
  277.   this._ops = [];
  278.  
  279.   // check if we need to disable the restore defaults button
  280.   var someHidden = this._defaultEngines.some(function (e) {return e.hidden;});
  281.   gEngineManagerDialog.showRestoreDefaults(someHidden);
  282. }
  283. EngineStore.prototype = {
  284.   _engines: null,
  285.   _defaultEngines: null,
  286.   _ops: null,
  287.  
  288.   get engines() {
  289.     return this._engines;
  290.   },
  291.   set engines(val) {
  292.     this._engines = val;
  293.     return val;
  294.   },
  295.  
  296.   _getIndexForEngine: function ES_getIndexForEngine(aEngine) {
  297.     return this._engines.indexOf(aEngine);
  298.   },
  299.  
  300.   _getEngineByName: function ES_getEngineByName(aName) {
  301.     for each (var engine in this._engines)
  302.       if (engine.name == aName)
  303.         return engine;
  304.  
  305.     return null;
  306.   },
  307.  
  308.   _cloneEngine: function ES_cloneObj(aEngine) {
  309.     var newO=[];
  310.     for (var i in aEngine)
  311.       newO[i] = aEngine[i];
  312.     newO.originalEngine = aEngine;
  313.     return newO;
  314.   },
  315.  
  316.   // Callback for Array's some(). A thisObj must be passed to some()
  317.   _isSameEngine: function ES_isSameEngine(aEngineClone) {
  318.     return aEngineClone.originalEngine == this.originalEngine;
  319.   },
  320.  
  321.   commit: function ES_commit() {
  322.     var searchService = Cc["@mozilla.org/browser/search-service;1"].
  323.                         getService(Ci.nsIBrowserSearchService);
  324.     var currentEngine = this._cloneEngine(searchService.currentEngine);
  325.     for (var i = 0; i < this._ops.length; i++)
  326.       this._ops[i].commit();
  327.  
  328.     // Restore currentEngine if it is a default engine that is still visible.
  329.     // Needed if the user deletes currentEngine and then restores it.
  330.     if (this._defaultEngines.some(this._isSameEngine, currentEngine) &&
  331.         !currentEngine.originalEngine.hidden)
  332.       searchService.currentEngine = currentEngine.originalEngine;
  333.   },
  334.  
  335.   addEngine: function ES_addEngine(aEngine) {
  336.     this._engines.push(this._cloneEngine(aEngine));
  337.   },
  338.  
  339.   moveEngine: function ES_moveEngine(aEngine, aNewIndex) {
  340.     if (aNewIndex < 0 || aNewIndex > this._engines.length - 1)
  341.       throw new Error("ES_moveEngine: invalid aNewIndex!");
  342.     var index = this._getIndexForEngine(aEngine);
  343.     if (index == -1)
  344.       throw new Error("ES_moveEngine: invalid engine?");
  345.  
  346.     if (index == aNewIndex)
  347.       return; // nothing to do
  348.  
  349.     // Move the engine in our internal store
  350.     var removedEngine = this._engines.splice(index, 1)[0];
  351.     this._engines.splice(aNewIndex, 0, removedEngine);
  352.  
  353.     this._ops.push(new EngineMoveOp(aEngine, aNewIndex));
  354.   },
  355.  
  356.   removeEngine: function ES_removeEngine(aEngine) {
  357.     var index = this._getIndexForEngine(aEngine);
  358.     if (index == -1)
  359.       throw new Error("invalid engine?");
  360.  
  361.     this._engines.splice(index, 1);
  362.     this._ops.push(new EngineRemoveOp(aEngine));
  363.     if (this._defaultEngines.some(this._isSameEngine, aEngine))
  364.       gEngineManagerDialog.showRestoreDefaults(true);
  365.   },
  366.  
  367.   restoreDefaultEngines: function ES_restoreDefaultEngines() {
  368.     var added = 0;
  369.  
  370.     for (var i = 0; i < this._defaultEngines.length; ++i) {
  371.       var e = this._defaultEngines[i];
  372.  
  373.       // If the engine is already in the list, just move it.
  374.       if (this._engines.some(this._isSameEngine, e)) {
  375.         this.moveEngine(this._getEngineByName(e.name), i);
  376.       } else {
  377.         // Otherwise, add it back to our internal store
  378.         this._engines.splice(i, 0, e);
  379.         this._ops.push(new EngineUnhideOp(e, i));
  380.         added++;
  381.       }
  382.     }
  383.     gEngineManagerDialog.showRestoreDefaults(false);
  384.     return added;
  385.   },
  386.  
  387.   changeEngine: function ES_changeEngine(aEngine, aProp, aNewValue) {
  388.     var index = this._getIndexForEngine(aEngine);
  389.     if (index == -1)
  390.       throw new Error("invalid engine?");
  391.  
  392.     this._engines[index][aProp] = aNewValue;
  393.     this._ops.push(new EngineChangeOp(aEngine, aProp, aNewValue));
  394.   },
  395.  
  396.   reloadIcons: function ES_reloadIcons() {
  397.     this._engines.forEach(function (e) {
  398.       e.uri = e.originalEngine.uri;
  399.     });
  400.   }
  401. }
  402.  
  403. function EngineView(aEngineStore) {
  404.   this._engineStore = aEngineStore;
  405. }
  406. EngineView.prototype = {
  407.   _engineStore: null,
  408.   tree: null,
  409.  
  410.   get lastIndex() {
  411.     return this.rowCount - 1;
  412.   },
  413.   get selectedIndex() {
  414.     var seln = this.selection;
  415.     if (seln.getRangeCount() > 0) {
  416.       var min = { };
  417.       seln.getRangeAt(0, min, { });
  418.       return min.value;
  419.     }
  420.     return -1;
  421.   },
  422.   get selectedEngine() {
  423.     return this._engineStore.engines[this.selectedIndex];
  424.   },
  425.  
  426.   // Helpers
  427.   rowCountChanged: function (index, count) {
  428.     this.tree.rowCountChanged(index, count);
  429.   },
  430.  
  431.   invalidate: function () {
  432.     this.tree.invalidate();
  433.   },
  434.  
  435.   ensureRowIsVisible: function (index) {
  436.     this.tree.ensureRowIsVisible(index);
  437.   },
  438.  
  439.   getSourceIndexFromDrag: function () {
  440.     var dragService = Cc["@mozilla.org/widget/dragservice;1"].
  441.                       getService().QueryInterface(Ci.nsIDragService);
  442.     var dragSession = dragService.getCurrentSession();
  443.     var transfer = Cc["@mozilla.org/widget/transferable;1"].
  444.                    createInstance(Ci.nsITransferable);
  445.  
  446.     transfer.addDataFlavor(ENGINE_FLAVOR);
  447.     dragSession.getData(transfer, 0);
  448.  
  449.     var dataObj = {};
  450.     var len = {};
  451.     var sourceIndex = -1;
  452.     try {
  453.       transfer.getAnyTransferData({}, dataObj, len);
  454.     } catch (ex) {}
  455.  
  456.     if (dataObj.value) {
  457.       sourceIndex = dataObj.value.QueryInterface(Ci.nsISupportsString).data;
  458.       sourceIndex = parseInt(sourceIndex.substring(0, len.value));
  459.     }
  460.  
  461.     return sourceIndex;
  462.   },
  463.  
  464.   // nsITreeView
  465.   get rowCount() {
  466.     return this._engineStore.engines.length;
  467.   },
  468.  
  469.   getImageSrc: function(index, column) {
  470.     if (column.id == "engineName" && this._engineStore.engines[index].iconURI)
  471.       return this._engineStore.engines[index].iconURI.spec;
  472.     return "";
  473.   },
  474.  
  475.   getCellText: function(index, column) {
  476.     if (column.id == "engineName")
  477.       return this._engineStore.engines[index].name;
  478.     else if (column.id == "engineKeyword")
  479.       return this._engineStore.engines[index].alias;
  480.     return "";
  481.   },
  482.  
  483.   setTree: function(tree) {
  484.     this.tree = tree;
  485.   },
  486.  
  487.   canDrop: function(targetIndex, orientation) {
  488.     var sourceIndex = this.getSourceIndexFromDrag();
  489.     return (sourceIndex != -1 &&
  490.             sourceIndex != targetIndex &&
  491.             sourceIndex != (targetIndex + orientation));
  492.   },
  493.  
  494.   drop: function(dropIndex, orientation) {
  495.     var sourceIndex = this.getSourceIndexFromDrag();
  496.     var sourceEngine = this._engineStore.engines[sourceIndex];
  497.  
  498.     if (dropIndex > sourceIndex) {
  499.       if (orientation == Ci.nsITreeView.DROP_BEFORE)
  500.         dropIndex--;
  501.     } else {
  502.       if (orientation == Ci.nsITreeView.DROP_AFTER)
  503.         dropIndex++;    
  504.     }
  505.  
  506.     this._engineStore.moveEngine(sourceEngine, dropIndex);
  507.     gEngineManagerDialog.showRestoreDefaults(true);
  508.  
  509.     // Redraw, and adjust selection
  510.     this.invalidate();
  511.     this.selection.clearSelection();
  512.     this.selection.select(dropIndex);
  513.   },
  514.  
  515.   selection: null,
  516.   getRowProperties: function(index, properties) { },
  517.   getCellProperties: function(index, column, properties) { },
  518.   getColumnProperties: function(column, properties) { },
  519.   isContainer: function(index) { return false; },
  520.   isContainerOpen: function(index) { return false; },
  521.   isContainerEmpty: function(index) { return false; },
  522.   isSeparator: function(index) { return false; },
  523.   isSorted: function(index) { return false; },
  524.   getParentIndex: function(index) { return -1; },
  525.   hasNextSibling: function(parentIndex, index) { return false; },
  526.   getLevel: function(index) { return 0; },
  527.   getProgressMode: function(index, column) { },
  528.   getCellValue: function(index, column) { },
  529.   toggleOpenState: function(index) { },
  530.   cycleHeader: function(column) { },
  531.   selectionChanged: function() { },
  532.   cycleCell: function(row, column) { },
  533.   isEditable: function(index, column) { return false; },
  534.   isSelectable: function(index, column) { return false; },
  535.   setCellValue: function(index, column, value) { },
  536.   setCellText: function(index, column, value) { },
  537.   performAction: function(action) { },
  538.   performActionOnRow: function(action, index) { },
  539.   performActionOnCell: function(action, index, column) { }
  540. };
  541.